// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using NUnit.Framework;

using AffineMatrixF = NPack.AffineMatrix<NPack.SingleComponent>;
using IVectorF = NPack.Interfaces.IVector<NPack.SingleComponent>;
using VectorF = NPack.Vector<NPack.SingleComponent>;

namespace NPack.Tests.Gdi
{
    [TestFixture]
    public class GdiAffineTransformTests
    {
        private static readonly Single _e = 0.0005F;

        [Test]
        public void RotationTest()
        {
            Matrix m1 = new Matrix();
			AffineMatrixF a1 = new AffineMatrixF(MatrixFormat.RowMajor, 3);

            m1.Rotate(45);
            a1.RotateAlong(null, Math.PI / 4);

            PointF[] gdiPoints = new PointF[] { new PointF(1, 0), new PointF(0, 1) };
            m1.TransformPoints(gdiPoints);

			VectorF[] npackPoints = new VectorF[] { new VectorF(1, 0, 1), new VectorF(0, 1, 1) };
			List<IVectorF> npackResults = new List<IVectorF>();
			npackResults.AddRange(a1.TransformVectors(npackPoints));

			Assert.AreEqual(m1.Elements[0], (Single)a1[0, 0], _e);
			Assert.AreEqual(m1.Elements[1], (Single)a1[0, 1], _e);
			Assert.AreEqual(m1.Elements[2], (Single)a1[1, 0], _e);
			Assert.AreEqual(m1.Elements[3], (Single)a1[1, 1], _e);

			Assert.AreEqual(gdiPoints[0].X, (Single)npackResults[0][0], _e);
			Assert.AreEqual(gdiPoints[0].Y, (Single)npackResults[0][1], _e);
			Assert.AreEqual(gdiPoints[1].X, (Single)npackResults[1][0], _e);
			Assert.AreEqual(gdiPoints[1].Y, (Single)npackResults[1][1], _e);
        }

		[Test]
		public void TranslateTest()
		{
			Matrix m1 = new Matrix();
            AffineMatrixF a1 = new AffineMatrixF(MatrixFormat.RowMajor, 3);

			m1.Translate(5, -10);
			a1.Translate(new VectorF(5, -10));

			PointF[] gdiPoints = new PointF[] { new PointF(1, 0), new PointF(0, 1) };
			m1.TransformPoints(gdiPoints);

			VectorF[] npackPoints = new VectorF[] { new VectorF(1, 0, 1), new VectorF(0, 1, 1) };
			List<IVectorF> npackResults = new List<IVectorF>();
			npackResults.AddRange(a1.TransformVectors(npackPoints));

			Assert.AreEqual(m1.Elements[0], (Single)a1[0, 0], _e);
			Assert.AreEqual(m1.Elements[1], (Single)a1[0, 1], _e);
			Assert.AreEqual(m1.Elements[2], (Single)a1[1, 0], _e);
			Assert.AreEqual(m1.Elements[3], (Single)a1[1, 1], _e);
			Assert.AreEqual(m1.Elements[4], (Single)a1[2, 0], _e);
			Assert.AreEqual(m1.Elements[5], (Single)a1[2, 1], _e);

			Assert.AreEqual(gdiPoints[0].X, (Single)npackResults[0][0], _e);
			Assert.AreEqual(gdiPoints[0].Y, (Single)npackResults[0][1], _e);
			Assert.AreEqual(gdiPoints[1].X, (Single)npackResults[1][0], _e);
			Assert.AreEqual(gdiPoints[1].Y, (Single)npackResults[1][1], _e);
		}

		[Test]
		public void ScaleTest()
		{
			Matrix m1 = new Matrix();
            AffineMatrixF a1 = new AffineMatrixF(MatrixFormat.RowMajor, 3);

			m1.Scale(100, -100);
			a1.Scale(new VectorF(100, -100));

			PointF[] gdiPoints = new PointF[] { new PointF(1, 0), new PointF(0, 1) };
			m1.TransformPoints(gdiPoints);

			VectorF[] npackPoints = new VectorF[] { new VectorF(1, 0, 1), new VectorF(0, 1, 1) };
			List<IVectorF> npackResults = new List<IVectorF>();
			npackResults.AddRange(a1.TransformVectors(npackPoints));

			Assert.AreEqual(m1.Elements[0], (Single)a1[0, 0], _e);
			Assert.AreEqual(m1.Elements[2], (Single)a1[0, 1], _e);
			Assert.AreEqual(m1.Elements[1], (Single)a1[1, 0], _e);
			Assert.AreEqual(m1.Elements[3], (Single)a1[1, 1], _e);
			Assert.AreEqual(m1.Elements[4], (Single)a1[0, 2], _e);
			Assert.AreEqual(m1.Elements[5], (Single)a1[1, 2], _e);

			Assert.AreEqual(gdiPoints[0].X, (Single)npackResults[0][0], _e);
			Assert.AreEqual(gdiPoints[0].Y, (Single)npackResults[0][1], _e);
			Assert.AreEqual(gdiPoints[1].X, (Single)npackResults[1][0], _e);
			Assert.AreEqual(gdiPoints[1].Y, (Single)npackResults[1][1], _e);
		}

		[Test]
		public void RotateAtTest()
		{
			Matrix m1 = new Matrix();
            AffineMatrixF a1 = new AffineMatrixF(MatrixFormat.RowMajor, 3);

			m1.RotateAt(180, new PointF(10, 0));
			a1.RotateAt(new VectorF(10, 0), null, Math.PI);

			PointF[] gdiPoints = new PointF[] { new PointF(1, 0), new PointF(0, 1) };
			m1.TransformPoints(gdiPoints);

			VectorF[] npackPoints = new VectorF[] { new VectorF(1, 0, 1), new VectorF(0, 1, 1) };
			List<IVectorF> npackResults = new List<IVectorF>();
			npackResults.AddRange(a1.TransformVectors(npackPoints));

			Assert.AreEqual(m1.Elements[0], (Single)a1[0, 0], _e);
			Assert.AreEqual(m1.Elements[1], (Single)a1[0, 1], _e);
			Assert.AreEqual(m1.Elements[2], (Single)a1[1, 0], _e);
			Assert.AreEqual(m1.Elements[3], (Single)a1[1, 1], _e);
			Assert.AreEqual(m1.Elements[4], (Single)a1[2, 0], _e);
			Assert.AreEqual(m1.Elements[5], (Single)a1[2, 1], _e);

			Assert.AreEqual(gdiPoints[0].X, (Single)npackResults[0][0], _e);
			Assert.AreEqual(gdiPoints[0].Y, (Single)npackResults[0][1], _e);
			Assert.AreEqual(gdiPoints[1].X, (Single)npackResults[1][0], _e);
			Assert.AreEqual(gdiPoints[1].Y, (Single)npackResults[1][1], _e);
		}

		[Test]
        [Ignore]
		public void ShearTest()
		{
		}

		[Test]
		public void CombinedTransformsTest()
        {
            Matrix m1 = new Matrix();
            AffineMatrixF a1 = new AffineMatrixF(MatrixFormat.RowMajor, 3);

            m1.Rotate(45);
            m1.Translate(10, 103, MatrixOrder.Append);
            m1.Scale(-1, 13, MatrixOrder.Append);
            m1.RotateAt(30, new PointF(33, 33), MatrixOrder.Append);

			a1.RotateAlong(null, Math.PI / 4);
			a1.Translate(new VectorF(10, 103));
            a1.Scale(new VectorF(-1, 13));
            a1.RotateAt(new VectorF(33, 33), null, Math.PI / 6);

			Assert.AreEqual(m1.Elements[0], (Single)a1[0, 0], _e);
			Assert.AreEqual(m1.Elements[1], (Single)a1[0, 1], _e);
			Assert.AreEqual(m1.Elements[2], (Single)a1[1, 0], _e);
			Assert.AreEqual(m1.Elements[3], (Single)a1[1, 1], _e);
			Assert.AreEqual(m1.Elements[4], (Single)a1[2, 0], _e);
			Assert.AreEqual(m1.Elements[5], (Single)a1[2, 1], _e);

			PointF[] gdiPoints = new PointF[] { new PointF(1, 0), new PointF(0, 1) };
			m1.TransformPoints(gdiPoints);

			VectorF[] npackPoints = new VectorF[] { new VectorF(1, 0, 1), new VectorF(0, 1, 1) };
			List<IVectorF> npackResults = new List<IVectorF>();
			npackResults.AddRange(a1.TransformVectors(npackPoints));

			Assert.AreEqual(gdiPoints[0].X, (Single)npackResults[0][0], _e);
			Assert.AreEqual(gdiPoints[0].Y, (Single)npackResults[0][1], _e);
			Assert.AreEqual(gdiPoints[1].X, (Single)npackResults[1][0], _e);
			Assert.AreEqual(gdiPoints[1].Y, (Single)npackResults[1][1], _e);
		}
    }
}
